#include <iostream>
#include <cstdlib>
#include <string>
#include <fstream>
using namespace std;

#include <boost/program_options.hpp>
namespace bpo = boost::program_options;


#include "hhvsimple.hpp"

// ====================================================

const string inFileDefault = "image.h5";
const string outFileDefault = "image.pgm";

string inFile( "no input" );
string outFile( "no output" );
string varName;


// =====================================================

void ReadCommandLine( int ac, char* av[] ) {

  try {
    bpo::options_description desc( "Allowed options" );

    desc.add_options()
      ("help", "Produce help message")
      ("name", bpo::value<string>(&varName), "Name of dataset in HDF5 file (defaults to first one found)" )
      ;

    bpo::options_description hidden( "Hidden, positional options");
    hidden.add_options()
      ("input", bpo::value<string>(&inFile), "Name of the input file")
      ("output", bpo::value<string>(&outFile), "Name of the output file" )
      ;

    bpo::positional_options_description posOpt;
    posOpt.add( "input", 1 );
    posOpt.add( "output", 2 );

    bpo::options_description cmdLineOpts;
    cmdLineOpts.add(desc).add(hidden);

    bpo::variables_map vm;
    bpo::store( bpo::command_line_parser( ac, av ).options(cmdLineOpts).positional(posOpt).run(), vm );
    bpo::notify( vm );

    if( vm.count( "help" ) ) {
      cout << "h52pgm [options] <input file> <output file>" << endl;
      cout << desc << endl;
      exit( EXIT_SUCCESS );
    }
  }

  catch( exception& e ) {
    cerr << "Error: " << e.what() << endl;
    exit( EXIT_FAILURE );
  }
  catch( ... ) {
    cerr << "Unknown exception" << endl;
    exit( EXIT_FAILURE );
  }
  
}




// ==============================

int main( int argc, char *argv[] ) {

  SciGPU::HHV::HHVolumeSimple<long,2> imageVals;

  cout << "HDF5 to PGM convertor" << endl;
  
  ReadCommandLine( argc, argv );


  // ------------------------------
  // Read the input file
  imageVals.ReadHDF5( inFile, varName );

  // Find the limits
  size_t xPix, yPix;
  xPix = imageVals.dimensions()[0];
  yPix = imageVals.dimensions()[1];


  imageVals.Recv();

  unsigned int maxVal = 0;
  for( unsigned int iy=0; iy<yPix; iy++ ) {
    for( unsigned int ix=0; ix<xPix; ix++ ) {
      if( imageVals(ix,iy) > maxVal ) {
        maxVal = imageVals(ix,iy);
      }
    }
  }

  cout << "Size is ( " << xPix << ", " << yPix << " )" << endl;
  cout << "Max value is " << maxVal << endl;
  
  // ---------------------------------
  // Open the output file

  ofstream pgmFile( outFile.c_str() );

  pgmFile << "P2" << endl;
  pgmFile << "# Converted from HDF5" << endl;
  pgmFile << setw(8) << xPix << setw(8) << yPix << endl;
  pgmFile << maxVal << endl;

   for( unsigned int iy=0; iy<yPix; iy++ ) {
    for( unsigned int ix=0; ix<xPix; ix++ ) {
      pgmFile << setw(5) << imageVals(ix,iy);
    }
    pgmFile << endl;
  }

  return( EXIT_SUCCESS );
}
